package view;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JPanel;

import darksideoftheloom.WeavingDraft;

public class BeweaveWeaveDraftPanel extends JPanel {
    private final int DRAWDOWN_LEFT_X = 20;
    private final int DRAWDOWN_TOP_Y;
    private final int DRAWDOWN_WIDTH = 572;
    private final int DRAWDOWN_HEIGHT = 390;
    private final int DRAWDOWN_NUMBER_ROWS = 30;
    private final int DRAWDOWN_NUMBER_COLUMNS = 44;

    private final int THREADING_LEFT_X;
    private final int THREADING_TOP_Y = 30;
    private final int THREADING_WIDTH;
    private final int THREADING_HEIGHT = 104;
    private final int THREADING_NUMBER_ROWS = 8;
    private final int THREADING_NUMBER_COLUMNS;

    private final int THREADLING_LEFT_X;
    private final int THREADLING_TOP_Y;
    private final int THREADLING_WIDTH = 104;
    private final int THREADLING_HEIGHT;
    private final int THREADLING_NUMBER_ROWS;
    private final int THREADLING_NUMBER_COLUMNS = 8;

    private final int TIEUP_LEFT_X;
    private final int TIEUP_TOP_Y;
    private final int TIEUP_WIDTH;
    private final int TIEUP_HEIGHT;
    private final int TIEUP_NUMBER_ROWS;
    private final int TIEUP_NUMBER_COLUMNS;

    private final int GRID_BLOCK_WIDTH_SIZE;
    private final int GRID_BLOCK_HEIGHT_SIZE;
    
    private JPanel panel = new JPanel();
    private JPanel my_panel;

    private WeavingDraft my_weaving_draft = new WeavingDraft(
            THREADING_NUMBER_ROWS, DRAWDOWN_NUMBER_COLUMNS,
            DRAWDOWN_NUMBER_ROWS, THREADLING_NUMBER_COLUMNS);

    public BeweaveWeaveDraftPanel(final JPanel the_panel) {
        super();
        my_panel = the_panel;
        DRAWDOWN_TOP_Y = 20 + THREADING_TOP_Y + THREADING_HEIGHT;
        THREADING_LEFT_X = DRAWDOWN_LEFT_X;
        THREADING_WIDTH = DRAWDOWN_WIDTH;
        THREADING_NUMBER_COLUMNS = DRAWDOWN_NUMBER_COLUMNS;
        THREADLING_LEFT_X = 20 + DRAWDOWN_LEFT_X + DRAWDOWN_WIDTH;
        THREADLING_TOP_Y = 20 + THREADING_TOP_Y + THREADING_HEIGHT;
        THREADLING_HEIGHT = DRAWDOWN_HEIGHT;
        THREADLING_NUMBER_ROWS = DRAWDOWN_NUMBER_ROWS;
        TIEUP_LEFT_X = THREADLING_LEFT_X;
        TIEUP_TOP_Y = THREADING_TOP_Y;
        TIEUP_WIDTH = THREADLING_WIDTH;
        TIEUP_HEIGHT = THREADING_HEIGHT;
        TIEUP_NUMBER_ROWS = THREADING_NUMBER_ROWS;
        TIEUP_NUMBER_COLUMNS = THREADLING_NUMBER_COLUMNS;

        GRID_BLOCK_WIDTH_SIZE = (int) THREADING_WIDTH
                / THREADING_NUMBER_COLUMNS;
        GRID_BLOCK_HEIGHT_SIZE = (int) THREADING_HEIGHT / THREADING_NUMBER_ROWS;

        addMouseListener(new MouseHandler());
        panel.setLayout(new BorderLayout());
        panel.add(this, BorderLayout.CENTER);
    }
    
    public JPanel getPanel() {
        panel.add(new JButton(new AbstractAction("Save"){
            public void actionPerformed(final ActionEvent the_event) {
                CardLayout cl = (CardLayout) my_panel.getLayout();
                ((BeweaveAttendeePanel) my_panel.getComponent(3))
                        .showSubmissions();
                cl.show(my_panel, "submit");
            }
        }), BorderLayout.SOUTH);
        
        return panel;
    }
    
    public void refresh() {
        my_weaving_draft = new WeavingDraft(
                THREADING_NUMBER_ROWS, DRAWDOWN_NUMBER_COLUMNS,
                DRAWDOWN_NUMBER_ROWS, THREADLING_NUMBER_COLUMNS);
    }
    
    public WeavingDraft getDraft() {
        return my_weaving_draft;
    }

    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        
        g2.setColor(Color.WHITE);
        g2.fill(new Rectangle2D.Double(0,0,800,600));
        g2.setColor(Color.BLACK);

        // draw DrawDown horizontal lines.
        for (int i = 0; i < DRAWDOWN_NUMBER_ROWS + 1; i++) {
            g2.draw(new Line2D.Double(DRAWDOWN_LEFT_X,
                    (i * GRID_BLOCK_HEIGHT_SIZE) + DRAWDOWN_TOP_Y,
                    DRAWDOWN_LEFT_X + DRAWDOWN_WIDTH,
                    (i * GRID_BLOCK_HEIGHT_SIZE) + DRAWDOWN_TOP_Y));
        }
        // draw DrawDown vertical lines.
        for (int i = 0; i < DRAWDOWN_NUMBER_COLUMNS + 1; i++) {
            g2.draw(new Line2D.Double((i * GRID_BLOCK_WIDTH_SIZE)
                    + DRAWDOWN_LEFT_X, DRAWDOWN_TOP_Y,
                    (i * GRID_BLOCK_WIDTH_SIZE) + DRAWDOWN_LEFT_X,
                    DRAWDOWN_TOP_Y + DRAWDOWN_HEIGHT));
        }

        // draw Threading horizontal lines.
        for (int i = 0; i < THREADING_NUMBER_ROWS + 1; i++) {
            g2.draw(new Line2D.Double(THREADING_LEFT_X,
                    (i * GRID_BLOCK_HEIGHT_SIZE) + THREADING_TOP_Y,
                    THREADING_LEFT_X + THREADING_WIDTH,
                    (i * GRID_BLOCK_HEIGHT_SIZE) + THREADING_TOP_Y));
        }
        // draw Threading vertical lines.
        for (int i = 0; i < THREADING_NUMBER_COLUMNS + 1; i++) {
            g2.draw(new Line2D.Double((i * GRID_BLOCK_WIDTH_SIZE)
                    + THREADING_LEFT_X, THREADING_TOP_Y,
                    (i * GRID_BLOCK_WIDTH_SIZE) + THREADING_LEFT_X,
                    THREADING_TOP_Y + THREADING_HEIGHT));
        }

        // draw Threadling horizontal lines.
        for (int i = 0; i < THREADLING_NUMBER_ROWS + 1; i++) {
            g2.draw(new Line2D.Double(THREADLING_LEFT_X,
                    (i * GRID_BLOCK_HEIGHT_SIZE) + THREADLING_TOP_Y,
                    THREADLING_LEFT_X + THREADLING_WIDTH,
                    (i * GRID_BLOCK_HEIGHT_SIZE) + THREADLING_TOP_Y));
        }
        // draw Threadling vertical lines.
        for (int i = 0; i < THREADLING_NUMBER_COLUMNS + 1; i++) {
            g2.draw(new Line2D.Double((i * GRID_BLOCK_WIDTH_SIZE)
                    + THREADLING_LEFT_X, THREADLING_TOP_Y,
                    (i * GRID_BLOCK_WIDTH_SIZE) + THREADLING_LEFT_X,
                    THREADLING_TOP_Y + THREADLING_HEIGHT));
        }

        // draw Treadling horizontal lines.
        for (int i = 0; i < TIEUP_NUMBER_ROWS + 1; i++) {
            g2.draw(new Line2D.Double(TIEUP_LEFT_X,
                    (i * GRID_BLOCK_HEIGHT_SIZE) + TIEUP_TOP_Y, TIEUP_LEFT_X
                            + TIEUP_WIDTH, (i * GRID_BLOCK_HEIGHT_SIZE)
                            + TIEUP_TOP_Y));
        }
        // draw Treadling vertical lines.
        for (int i = 0; i < TIEUP_NUMBER_COLUMNS + 1; i++) {
            g2.draw(new Line2D.Double((i * GRID_BLOCK_WIDTH_SIZE)
                    + TIEUP_LEFT_X, TIEUP_TOP_Y, (i * GRID_BLOCK_WIDTH_SIZE)
                    + TIEUP_LEFT_X, TIEUP_TOP_Y + TIEUP_HEIGHT));
        }
        /*
         * Rectangle2D block = new
         * Rectangle2D.Double((the_x*GRID_BLOCK_WIDTH_SIZE) + the_left_x,
         * (the_y*GRID_BLOCK_HEIGHT_SIZE) + the_top_y, GRID_BLOCK_WIDTH_SIZE,
         * GRID_BLOCK_HEIGHT_SIZE);
         */

        boolean[][] current_array = my_weaving_draft.getDrawdown();

        for (int i = 0; i < DRAWDOWN_NUMBER_ROWS; i++) {
            for (int j = 0; j < DRAWDOWN_NUMBER_COLUMNS; j++) {
                if (current_array[i][j])
                    g2.fill(new Rectangle2D.Double((j * GRID_BLOCK_WIDTH_SIZE)
                            + DRAWDOWN_LEFT_X, (i * GRID_BLOCK_HEIGHT_SIZE)
                            + DRAWDOWN_TOP_Y, GRID_BLOCK_WIDTH_SIZE,
                            GRID_BLOCK_HEIGHT_SIZE));
            }
        }

        current_array = my_weaving_draft.getThreading();

        for (int i = 0; i < THREADING_NUMBER_ROWS; i++) {
            for (int j = 0; j < THREADING_NUMBER_COLUMNS; j++) {
                if (current_array[i][j]) {
                    g2.fill(new Rectangle2D.Double((j * GRID_BLOCK_WIDTH_SIZE)
                            + THREADING_LEFT_X, (i * GRID_BLOCK_HEIGHT_SIZE)
                            + THREADING_TOP_Y, GRID_BLOCK_WIDTH_SIZE,
                            GRID_BLOCK_HEIGHT_SIZE));
                }
            }
        }

        current_array = my_weaving_draft.getTreadling();

        for (int i = 0; i < THREADLING_NUMBER_ROWS; i++) {
            for (int j = 0; j < THREADLING_NUMBER_COLUMNS; j++) {
                if (current_array[i][j]) {
                    g2.fill(new Rectangle2D.Double((j * GRID_BLOCK_WIDTH_SIZE)
                            + THREADLING_LEFT_X, (i * GRID_BLOCK_HEIGHT_SIZE)
                            + THREADLING_TOP_Y, GRID_BLOCK_WIDTH_SIZE,
                            GRID_BLOCK_HEIGHT_SIZE));
                }
            }
        }

        current_array = my_weaving_draft.getTieUp();

        for (int i = 0; i < TIEUP_NUMBER_ROWS; i++) {
            for (int j = 0; j < TIEUP_NUMBER_COLUMNS; j++) {
                if (current_array[i][j]) {
                    g2.fill(new Rectangle2D.Double((j * GRID_BLOCK_WIDTH_SIZE)
                            + TIEUP_LEFT_X, (i * GRID_BLOCK_HEIGHT_SIZE)
                            + TIEUP_TOP_Y, GRID_BLOCK_WIDTH_SIZE,
                            GRID_BLOCK_HEIGHT_SIZE));
                }
            }
        }
    }

    private class MouseHandler extends MouseAdapter {
        public void mouseClicked(MouseEvent event) {

            if ((int) event.getPoint().getX() > THREADING_LEFT_X
                    && (int) event.getPoint().getX() < (THREADING_LEFT_X + THREADING_WIDTH)
                    && (int) event.getPoint().getY() > THREADING_TOP_Y
                    && (int) event.getPoint().getY() < (THREADING_TOP_Y + THREADING_HEIGHT)) {
                int x = (int) ((event.getPoint().getX() - THREADING_LEFT_X) / GRID_BLOCK_WIDTH_SIZE);
                int y = (int) ((event.getPoint().getY() - THREADING_TOP_Y) / GRID_BLOCK_HEIGHT_SIZE);

                my_weaving_draft.changeThreading(y, x);

            } else if ((int) event.getPoint().getX() > THREADLING_LEFT_X
                    && (int) event.getPoint().getX() < (THREADLING_LEFT_X + THREADLING_WIDTH)
                    && (int) event.getPoint().getY() > THREADLING_TOP_Y
                    && (int) event.getPoint().getY() < (THREADLING_TOP_Y + THREADLING_HEIGHT)) {
                int x = (int) ((event.getPoint().getX() - THREADLING_LEFT_X) / GRID_BLOCK_WIDTH_SIZE);
                int y = (int) ((event.getPoint().getY() - THREADLING_TOP_Y) / GRID_BLOCK_HEIGHT_SIZE);

                my_weaving_draft.changeTreadling(y, x);

            } else if ((int) event.getPoint().getX() > TIEUP_LEFT_X
                    && (int) event.getPoint().getX() < (TIEUP_LEFT_X + TIEUP_WIDTH)
                    && (int) event.getPoint().getY() > TIEUP_TOP_Y
                    && (int) event.getPoint().getY() < (TIEUP_TOP_Y + TIEUP_HEIGHT)) {
                int x = (int) ((event.getPoint().getX() - TIEUP_LEFT_X) / GRID_BLOCK_WIDTH_SIZE);
                int y = (int) ((event.getPoint().getY() - TIEUP_TOP_Y) / GRID_BLOCK_HEIGHT_SIZE);

                my_weaving_draft.changeTieUp(y, x);
            }
            repaint();
        }
    }
}
